feat(analytics): consume server-bootstrapped landing-variant flag (#39)#40
feat(analytics): consume server-bootstrapped landing-variant flag (#39)#40kilbot wants to merge 1 commit into
Conversation
Read window.wcpos.landing.bootstrap_flags (injected by plugin >=1.9.7) into
posthog.init's bootstrap.featureFlags so getFeatureFlag('landing-variant')
resolves synchronously at first paint -- no /flags network fetch, no 500ms
cold-path timeout, no flicker.
The self-hosted PostHog /flags endpoint rejects the public token (401), so the
in-browser flag fetch never resolved (zero render_source:flag events across all
visitors); the server-side bootstrap sidesteps the broken endpoint entirely.
- landing-data.ts: add optional `bootstrap_flags` (Record<string,string|boolean>)
to the WCPOSLanding contract + `isFlagMap` validation in getLandingData.
- analytics.ts: seed bootstrap.featureFlags from data.bootstrap_flags. Skipped in
preview, which seeds its own assignment cache and must not resolve prod flags.
- Rebuilt assets/js/welcome.js.
- Tests for the contract, the validation guard, and the bootstrap wiring.
Companion plugin change that injects the data: wcpos/woocommerce-pos#1189.
Closes #39
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: wcpos/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds an optional ChangesServer-resolved feature flags bootstrap
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f6ee21937a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // 500 ms cold-path timeout, no flicker. Absent on older plugins | ||
| // (the cold path then resolves it). Skipped in preview, which seeds | ||
| // its own assignment cache and must not resolve production flags. | ||
| ...(!preview && data?.bootstrap_flags ? { featureFlags: data.bootstrap_flags } : {}), |
There was a problem hiding this comment.
Bootstrap flags outside the new-identity branch
When a browser already has ph_${POSTHOG_KEY}_posthog but no valid wcpos_landing_assignment (for example, anyone who loaded the previous broken /flags cold path, or after the assignment cache expires), this spread is never reached because it is nested under anonId && !hasPersistedIdentity(). prepareVariant() then waits on the still-broken flag endpoint, gets no bootstrapped landing-variant, and renders fallback again, so the server-resolved assignment does not take effect for returning users. Keep the distinctID bootstrapping gated, but pass bootstrap.featureFlags whenever bootstrap_flags is present except in preview.
Useful? React with 👍 / 👎.
Summary
Consumes the server-resolved
landing-variantvalue so the A/B test renders the assigned variant at first paint instead of racing a (broken) in-browser flag fetch. Companion to wcpos/woocommerce-pos#1189.shared/landing-data.ts— add optionalbootstrap_flags?: Record<string, string | boolean>to theWCPOSLandingcontract, with anisFlagMapguard, validated/included ingetLandingData().shared/analytics.ts— seedposthog.init'sbootstrap.featureFlagsfromdata.bootstrap_flags, sogetFeatureFlag('landing-variant')returns synchronously. Skipped in preview (the GitHub Pages harness seeds its own assignment cache and must not resolve production flags).assets/js/welcome.js; tests for the contract, the guard, and the bootstrap wiring.Why the cold path never worked
The in-browser fetch wasn't merely slow — the self-hosted PostHog flags endpoint rejects the public token:
POST /capture/→ 200, butPOST /flags/?v=2&config=true→ 401 andPOST /decide/?v=3→ 403 CSRF. Soposthog-jsgotundefinedevery time → zerorender_source:flagevents across all 337 visitors. Raising the 500 ms timeout would not have helped. Bootstrapping the value (resolved server-side in the plugin via PostHog's consistent-hash) makes the decision independent of that endpoint — theresolveFlagcold path now resolves instantly via the bootstrapped value and writes the cache, with no flicker.Design decisions (preserve through rebases)
featureFlagsis skipped whenpreviewis true — preview seeds its own assignment cache; resolving production flags there would pollute baselines (consistent withadvanced_disable_flags: preview).bootstrap_flagsis optional and guarded — older plugins (<1.9.7) don't inject it;getLandingDatasimply omits it and the existing cold path resolves the variant (now that the plugin also stops identifying early).assets/js/welcome.jsis committed —assets/is tracked andcheck:assetsrequires it to match a fresh build. Only the bootstrap entry changed; variant chunks rebuilt byte-identical.Companion PRs / cross-repo
window.wcpos.landing.bootstrap_flagsand stops the plugin's earlyposthog.init/identify()on the welcome page (which was poisoning this bundle's shared localStorage identity). Both must ship for the experiment to go green./flags+/decideendpoints onph.wcpos.comneed fixing so client-side flag reloads, experience-continuity, and future experiment flags work. The bootstrap sidesteps this forlanding-variantbut does not fix it.Test plan
npm run cipasses (typecheck, 41 tests, lint:*, check:assets) — green locally.bootstrap_flags, load the welcome screen: the assigned variant renders with no flash of default, and alanding_variant_renderedevent fires withrender_source: flag.$feature_flag_calledforlanding-variantcarries a non-empty$feature_flag_response.bootstrap_flags: page still loads, no errors (cold path resolves or falls back).Closes #39
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests